package com.yygo.webapp.controller.attachment;

import com.yygo.Constants;
import com.yygo.configentity.attachment.RoleAttachment;
import com.yygo.model.Attachment;
import com.yygo.model.LoanRequest;
import com.yygo.model.User;
import com.yygo.model.enums.AttachmentType;
import com.yygo.service.LoanRequestManager;
import com.yygo.service.UserManager;
import com.yygo.webapp.controller.BaseFormController;
import com.yygo.webapp.controller.FileUpload;
import org.appfuse.service.GenericManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.mail.internet.MimeUtility;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by stella on 2015/11/29.
 */
@Controller
@RequestMapping("/uploadCaFile")
public class UploadCaFileController extends BaseFormController {
    private LoanRequestManager loanRequestManager;

    private GenericManager<Attachment, Long> attachmentManager = null;

    @Autowired
    public void setAttachmentManager(@Qualifier("attachmentManager") GenericManager<Attachment, Long> attachmentManager) {
        this.attachmentManager = attachmentManager;
    }

    @Autowired
    public void setLoanRequestManager(@Qualifier("loanRequestManager") LoanRequestManager loanRequestManager) {
        this.loanRequestManager = loanRequestManager;
    }

    @Autowired
    private UserManager userManager;

    @RequestMapping(method = RequestMethod.GET)
    public Model handleRequest(@RequestParam(required = true, value = "reqId") Long reqId, @RequestParam(required = true, value="type") String type,  HttpServletRequest request)
            throws Exception {
        Model model = new ExtendedModelMap();
        LoanRequest loanRequest = loanRequestManager.getLoanRequest(reqId);
        model.addAttribute(loanRequest);
        return model;
    }

    @RequestMapping(method = RequestMethod.POST)
    public String onSubmit(FileUpload fileUpload, BindingResult errors, HttpServletRequest request, Principal principal)
            throws Exception {

        if (validator != null) { // validator is null during testing
            validator.validate(fileUpload, errors);
            if (errors.hasErrors()) {
                return "uploadCaFile";
            }
        }

        // validate a file was entered
        if (fileUpload.getFile().length == 0) {
            Object[] args =
                    new Object[]{getText("uploadForm.file", request.getLocale())};
            errors.rejectValue("file", "errors.required", args, "File");
            return "uploadCaFile";
        }

        LoanRequest loanRequest = loanRequestManager.loadWholeLoanRequest(fileUpload.getReqId());
        User loginUser = userManager.getUserByUsername(principal.getName());

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        CommonsMultipartFile file = (CommonsMultipartFile) multipartRequest.getFile("file");

        // the directory to upload to
        String name = fileUpload.getName();
        String type = fileUpload.getType();
        String uploadDir = getUploadPath();
        uploadDir += File.separator + loanRequest.getNumber() + File.separator + type;

        // Create the directory if it doesn't exist
        File dirPath = new File(uploadDir);

        if (!dirPath.exists()) {
            dirPath.mkdirs();
        }

        //retrieve the file data
        InputStream stream = file.getInputStream();

        //write the file to the file specified
        OutputStream bos = new FileOutputStream(uploadDir + File.separator + file.getOriginalFilename());
        int bytesRead;
        byte[] buffer = new byte[8192];

        while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
            bos.write(buffer, 0, bytesRead);
        }

        bos.close();

        //close the stream
        stream.close();

        Long attachmentId = findAttachmentId(loanRequest, type);
        //check if the file is uploaded before.
        if(attachmentId!=null){
            Attachment attachment = attachmentManager.get(attachmentId);
            attachment.setFileName(file.getOriginalFilename());
            attachment.setTime(new Date());
            attachment.setOperator(request.getRemoteUser());
            attachmentManager.save(attachment);
        }else{
            Attachment attachment = new Attachment();
            attachment.setLoanRequest(loanRequest);
            attachment.setName(name);
            if(type.equals("businessForm")){
                attachment.setType(AttachmentType.BusinessForm);
            } else if(type.equals("auditResult")){
                attachment.setType(AttachmentType.AuditResult);
            } else if(type.equals("insuranceForm")){
                attachment.setType(AttachmentType.InsuranceForm);
            } else if(type.equals("creditForm")){
                attachment.setType(AttachmentType.CreditForm);
            } else {
                attachment.setType(AttachmentType.CA_Audit);
            }

            attachment.setTime(new Date());
            attachment.setFileName(file.getOriginalFilename());
            attachment.setOperator(request.getRemoteUser());
            attachmentManager.save(attachment);
        }
        saveMessage(request, getText("attachment.updated", request.getLocale()));
        return "redirect:/loanRequestform?reqId=" + fileUpload.getReqId();
    }

    @RequestMapping(value="/download/{id}/{type}", method = RequestMethod.GET)
    public void getImage(@PathVariable Long id, @PathVariable String type, HttpServletResponse response) throws UnsupportedEncodingException {
        LoanRequest loanRequest = loanRequestManager.loadWholeLoanRequest(id);
        Long attachmentId = findAttachmentId(loanRequest, type);
        if(attachmentId==null){
            try {
                response.sendError(404, "attachment not found");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            Attachment attachment = attachmentManager.get(attachmentId);
            String fileName = attachment.getFileName();
            String uploadDir = getUploadPath();
            uploadDir += File.separator + loanRequest.getNumber() + File.separator + type;
            FileInputStream fis = null;
            if (fileName.toLowerCase().endsWith("xls") || fileName.toLowerCase().endsWith("doc")){
                response.setHeader("Content-Disposition", "attachment; filename=".concat(MimeUtility.encodeWord(fileName)));
                response.setContentType("application/octet-stream; charset=utf-8");
            }

            try {
                OutputStream out = response.getOutputStream();
                File file = new File(uploadDir + File.separator + fileName);
                fis = new FileInputStream(file);
                byte[] b = new byte[fis.available()];
                fis.read(b);
                out.write(b);
                out.flush();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private Long findAttachmentId(LoanRequest loanRequest, String type){
        for(Attachment attachment: loanRequest.getAttachmentList()){
            if (attachment.getType().toString().equals(type)){
                return attachment.getId();
            }
        }
        return null;
    }

    @ModelAttribute
    protected FileUpload showForm(HttpServletRequest request)
            throws Exception {
        return new FileUpload();
    }

    private String getUploadPath() {
        // the directory to upload to
        String uploadDir = getServletContext().getRealPath("/resources");

        // The following seems to happen when running jetty:run
        if (uploadDir == null) {
            uploadDir = new File("src/main/webapp/resources").getAbsolutePath();
        }
        //uploadDir += "/" + number + "/";
        return uploadDir;
    }

}
